<?php

    /**
	 * Authentification
	 *
	 * Driver for Authentification based on a database
	 *
     * @package      Drivers
     * @subpackage   Db_Authentification
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    class Drivers_Db_Authentification implements Core_Authentification_Interface
    {

    ////////////////////////////////////////////////////////////////////////////
    //                                Variables                               //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Zend_Auth object
         *
         * @var Zend_Auth
         */
        protected $_auth = null;

        /**
         * Zend_Auth_Storage_Session object
         *
         * @var Zend_Auth_Storage_Session
         */
        protected $_storage = null;

        /**
         * Results of database authentication query
         *
         * @var Security_Classes_Db_User
         */
        private $_resultUser = null;

	////////////////////////////////////////////////////////////////////////////
	//                            Getters / Setters                           //
	////////////////////////////////////////////////////////////////////////////

		/**
		 * Returns the namespace
		 *
		 * @return		Zend_Session_Namespace
		 */
		public function getNamespace()
		{
			return $this->_storage->read('Authentification');
		}

	////////////////////////////////////////////////////////////////////////////
	//                                 Methods                                //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Contructor
         *
         * @throws       Core_Exception
		 */
        public function __construct()
        {
            $this->_storage = new Zend_Auth_Storage_Session('Authentification');

            $this->_auth = Zend_Auth::getInstance();
            $this->_auth->setStorage($this->_storage);
        }

		/**
		 * Destructor
		 */
		public function __destruct()
		{
			unset($this);
		}

		/**
		 * Connects a user
		 *
		 * @param       string		$username : the user's identifier
		 * @param       string		$password : the user's identifier
         * @throws		Core_ArgumentException
         * @throws		Core_ArgumentNullException
		 * @return      Zend_Auth_Result
		 */
		public function login($username, $password)
        {
            if ($username === null) {
				throw new Core_ArgumentNullException('username is a null reference');
			}

            if (strlen(trim($username)) == 0) {
				throw new Core_ArgumentException('username is a zero-length string');
			}

            if ($password === null) {
				throw new Core_ArgumentNullException('password is a null reference');
			}

            if (strlen(trim($password)) == 0) {
				throw new Core_ArgumentException('password is a zero-length string');
			}

            $this->_resultUser = Doctrine_Query::create()
                                    ->from('DbAdmin')
                                    ->where('login = ?', array($username))
                                    ->fetchOne();

            if ($this->_resultUser instanceof DbAdmin) {
                if ($this->_resultUser->password != sha1($password)) {
                    return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
                } else {
                    $this->_storage->write($this->_getResultRowObject(null, 'password'));
                    return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, null);
                }
            } else {
                return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, null);
            }

            return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
		}

		/**
		 * Disconnects a user
		 *
		 * @return      void
		 */
		public function logoff()
        {
            Zend_Auth::getInstance()->clearIdentity();
            Zend_Session::namespaceUnset('Authentification');
		}

		/**
		 * Gets a value indicating wether the user is log in or not
		 *
		 * @return		boolean
		 */
		public function isConnected()
		{
			return (isset($this->getNamespace()->id)) ? true : false;
		}

	////////////////////////////////////////////////////////////////////////////
	//                             Private Methods                            //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Returns the result user as a stdClass object
         *
         * @param       string|array        $returnColumns
         * @param       string|array        $omitColumns
         * @return      stdClass|boolean    Return false on error
         */
        public function _getResultRowObject($returnColumns = null, $omitColumns = null)
        {
            if (!$this->_resultUser) {
                return false;
            }

            $returnObject = new stdClass();

            if ($returnColumns !== null) {
                $returnColumns = (array)$returnColumns;

                foreach ($this->_resultUser as $property => $value) {
                    if (in_array($property, $returnColumns)) {
                        $returnObject->{$property} = $value;
                    }
                }

                return $returnObject;
            } else if ($omitColumns !== null) {
                $omitColumns = (array)$omitColumns;

                foreach ($this->_resultUser as $property => $value) {
                    if (!in_array($property, $omitColumns)) {
                        $returnObject->{$property} = $value;
                    }
                }

                return $returnObject;
            } else {
                foreach ($this->_resultUser as $property => $value) {
                    $returnObject->{$property} = $value;
                }

                return $returnObject;
            }
        }
    }
